home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / kernel / lfs / lfsDesc.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-12-19  |  15.4 KB  |  523 lines

  1. /* 
  2.  * lfsDesc.c --
  3.  *
  4.  *    File descriptor management routines for LFS. The routine in 
  5.  *    this module provide the interface for file descriptors I/O 
  6.  *      and allocation for a LFS file system.   The implementation uses
  7.  *    the file system block cache to cache groups of descriptors and
  8.  *    provide write buffering. 
  9.  *
  10.  * Copyright 1989 Regents of the University of California
  11.  * Permission to use, copy, modify, and distribute this
  12.  * software and its documentation for any purpose and without
  13.  * fee is hereby granted, provided that the above copyright
  14.  * notice appear in all copies.  The University of California
  15.  * makes no representations about the suitability of this
  16.  * software for any purpose.  It is provided "as is" without
  17.  * express or implied warranty.
  18.  */
  19.  
  20. #ifndef lint
  21. static char rcsid[] = "$Header: /cdrom/src/kernel/Cvsroot/kernel/lfs/lfsDesc.c,v 1.11 92/06/01 15:03:53 kupfer Exp $ SPRITE (Berkeley)";
  22. #endif /* not lint */
  23.  
  24. #include <sprite.h>
  25. #include <lfs.h>
  26. #include <lfsInt.h>
  27. #include <lfsDesc.h>
  28. #include <lfsDescMap.h>
  29. #include <fs.h>
  30. #include <fsdm.h>
  31. #include <user/time.h>
  32.  
  33.  
  34. /*
  35.  * @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
  36.  * Start of routines exported to higher levels of the file system.
  37.  * @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
  38.  */
  39.  
  40.  
  41. /*
  42.  *----------------------------------------------------------------------
  43.  *
  44.  * Lfs_FileDescFetch() --
  45.  *
  46.  *    Fetch the specified file descriptor from the file system and 
  47.  *    store it in *fileDescPtr.
  48.  *
  49.  * Results:
  50.  *    An error if could not read the file descriptor from disk or is not
  51.  *    allocated.
  52.  *
  53.  * Side effects:
  54.  *    A block of descriptors may be read into the cache.
  55.  *
  56.  *----------------------------------------------------------------------
  57.  */
  58.  
  59. ReturnStatus
  60. Lfs_FileDescFetch(domainPtr, fileNumber, fileDescPtr)
  61.      Fsdm_Domain     *domainPtr;    /* Domain to fetch file descriptor. */
  62.      int        fileNumber;     /* Number of file descriptor to fetch.*/
  63.      Fsdm_FileDescriptor *fileDescPtr;    /* File descriptor structure to fetch.*/
  64. {
  65.     Lfs    *lfsPtr = LfsFromDomainPtr(domainPtr);
  66.     LfsFileDescriptor    *descPtr;
  67.     Fscache_Block        *blockPtr;
  68.     ReturnStatus    status;
  69.     LfsDiskAddr           diskAddr;
  70.     int        i, cacheFlags;
  71.     Boolean    found;
  72.  
  73.     LFS_STATS_INC(lfsPtr->stats.desc.fetches);
  74.     status = LfsDescMapGetDiskAddr(lfsPtr, fileNumber, &diskAddr);
  75.     if (status != SUCCESS) {
  76.     return status;
  77.     }
  78.     cacheFlags = FSCACHE_DESC_BLOCK;
  79.     if (LfsIsCleanerProcess(lfsPtr)) {
  80.     cacheFlags |= FSCACHE_CANT_BLOCK;
  81.     LFS_STATS_INC(lfsPtr->stats.desc.cleaningFetch);
  82.    }
  83.     /*
  84.      * See if the value is in the descriptor block cache. If it is not 
  85.      * then read it in.
  86.      */
  87.     Fscache_FetchBlock(&lfsPtr->descCache.handle.cacheInfo, 
  88.               LfsDiskAddrToOffset(diskAddr), cacheFlags,
  89.                &blockPtr, &found);
  90.     if (!found) {
  91.     LFS_STATS_INC(lfsPtr->stats.desc.fetchCacheMiss);
  92.     if (LfsIsCleanerProcess(lfsPtr) &&
  93.         (!lfsPtr->segCache.valid ||
  94.          !LfsDiskAddrInRange(diskAddr, LfsBytesToBlocks(lfsPtr, 4096),
  95.                 lfsPtr->segCache.startDiskAddress,
  96.                 lfsPtr->segCache.endDiskAddress))) {
  97.         LFS_STATS_INC(lfsPtr->stats.desc.cleaningFetchMiss);
  98.     }
  99.     status = LfsReadBytes(lfsPtr, diskAddr, 
  100.         lfsPtr->fileLayout.params.descPerBlock * sizeof(*descPtr),
  101.         blockPtr->blockAddr);
  102. #ifdef ERROR_CHECK
  103.      LfsCheckRead(lfsPtr, diskAddr, 
  104.         lfsPtr->fileLayout.params.descPerBlock * sizeof(*descPtr));
  105. #endif
  106.     if (status != SUCCESS) {
  107.         printf( "Could not read in file descriptor\n");
  108.         Fscache_UnlockBlock(blockPtr, (time_t)0, -1, 0,
  109.                 FSCACHE_DELETE_BLOCK);
  110.         return status;
  111.     }
  112.     }
  113.     descPtr = (LfsFileDescriptor *) (blockPtr->blockAddr);
  114.     for (i = 0; i < lfsPtr->fileLayout.params.descPerBlock; i++) {
  115.     /*
  116.      * The descriptor block is terminated by an inode
  117.      * with a zero magic number.
  118.      */
  119.     if (descPtr->common.magic == 0) {
  120.         break;
  121.     }
  122.     if (descPtr->common.magic != FSDM_FD_MAGIC) {
  123.         LfsError(lfsPtr, FAILURE, "Bad descriptor magic number.\n");
  124.         continue;
  125.     }
  126.     if (descPtr->fileNumber == fileNumber) {
  127.          LFS_STATS_INC(lfsPtr->stats.desc.goodFetch);
  128.          LFS_STATS_ADD(lfsPtr->stats.desc.fetchSearched,i);
  129.          bcopy((char *) &(descPtr->common), (char *)fileDescPtr,
  130.             sizeof(descPtr->common));
  131.          status = LfsDescMapGetAccessTime(lfsPtr, fileNumber,
  132.                 &(fileDescPtr->accessTime));
  133.          if (status != SUCCESS) {
  134.           LfsError(lfsPtr, status, "Can't get access time.\n");
  135.          }
  136.         Fscache_UnlockBlock(blockPtr, (time_t)0, -1, FS_BLOCK_SIZE, 0);
  137.         return SUCCESS;
  138.     }
  139.     descPtr++;
  140.     }
  141.     Fscache_UnlockBlock(blockPtr, (time_t)0, -1, 0, FSCACHE_DELETE_BLOCK);
  142.     printf("Descriptor map foulup, can't find file %d at %d\n", fileNumber,
  143.             LfsDiskAddrToOffset(diskAddr));
  144.     LfsError(lfsPtr, FS_FILE_NOT_FOUND, "Descriptor map foulup.");
  145.     return FS_FILE_NOT_FOUND;
  146.  
  147. }
  148.  
  149.  
  150. /*
  151.  *----------------------------------------------------------------------
  152.  *
  153.  * Lfs_FileDescStore() --
  154.  *    Store the given file descriptor back into the file system block
  155.  *    where it came from.  
  156.  *
  157.  * Results:
  158.  *    An error if could not read the file descriptor from disk or is not
  159.  *    allocated.
  160.  *
  161.  * Side effects:
  162.  *    A block of descriptors may be read into the cache.
  163.  *
  164.  *----------------------------------------------------------------------
  165.  */
  166.  
  167. ReturnStatus
  168. Lfs_FileDescStore(domainPtr, handlePtr, fileNumber, fileDescPtr, forceOut)
  169.     register Fsdm_Domain *domainPtr;    /* Domain to store the file 
  170.                      * descriptor into. */
  171.     Fsio_FileIOHandle    *handlePtr;
  172.     int            fileNumber;     /* Number of file descriptor to 
  173.                        store.*/
  174.     Fsdm_FileDescriptor    *fileDescPtr;     /* File descriptor to store. */
  175.     Boolean        forceOut;  /* Force the change to disk. */
  176. {
  177.     Lfs    *lfsPtr = LfsFromDomainPtr(domainPtr);
  178.     ReturnStatus    status = SUCCESS;
  179.  
  180.     LFS_STATS_INC(lfsPtr->stats.desc.stores);
  181.     if (fileDescPtr->flags & FSDM_FD_FREE) {
  182.     LFS_STATS_INC(lfsPtr->stats.desc.freeStores);
  183.     return SUCCESS;
  184.     }
  185.     if (fileDescPtr->flags & FSDM_FD_ACCESSTIME_DIRTY) {
  186.      status = LfsDescMapSetAccessTime(lfsPtr, fileNumber, 
  187.                  fileDescPtr->accessTime);
  188.       if (status != SUCCESS) {
  189.           LfsError(lfsPtr, status, "Can't update descriptor map.\n");
  190.           }
  191.       fileDescPtr->flags &= ~FSDM_FD_ACCESSTIME_DIRTY;
  192.       LFS_STATS_INC(lfsPtr->stats.desc.accessTimeUpdate);
  193.     }
  194.     if (fileDescPtr->flags & FSDM_FD_DIRTY) {
  195.     LFS_STATS_INC(lfsPtr->stats.desc.dirtyList);
  196.     Fscache_PutFileOnDirtyList(&handlePtr->cacheInfo, 
  197.                 FSCACHE_FILE_DESC_DIRTY);
  198.     }
  199.     return status;
  200. }
  201.  
  202. /*
  203.  *----------------------------------------------------------------------
  204.  *
  205.  * Lfs_FileTrunc --
  206.  *
  207.  *      Shorten a file to length bytes.  This updates the descriptor
  208.  *      and may free blocks and indirect blocks from the end of the file.
  209.  *
  210.  * Results:
  211.  *      Error if had problem with indirect blocks, otherwise SUCCESS.
  212.  *
  213.  * Side effects:
  214.  *      May modify the truncateVersion number.
  215.  *    Any allocated blocks after the given size are deleted.
  216.  *
  217.  *----------------------------------------------------------------------
  218.  */
  219.  
  220. ReturnStatus
  221. Lfs_FileTrunc(domainPtr, handlePtr, size, delete)
  222.     Fsdm_Domain        *domainPtr;
  223.     Fsio_FileIOHandle   *handlePtr;     /* File to truncate. */
  224.     int                 size;           /* Size to truncate the file to. */
  225.     Boolean        delete;        /* TRUE if Truncate for delete. */
  226. {
  227.     Lfs    *lfsPtr = LfsFromDomainPtr(domainPtr);
  228.     Fsdm_FileDescriptor    *descPtr;
  229.     ReturnStatus    status = SUCCESS;
  230.     int            newLastByte;
  231.  
  232.     if (size < 0) {
  233.     return(GEN_INVALID_ARG);
  234.     }
  235.     LFS_STATS_INC(lfsPtr->stats.desc.truncs);
  236.  
  237.     descPtr = handlePtr->descPtr;
  238.  
  239.     newLastByte = size - 1;
  240.     if (descPtr->lastByte <= newLastByte) {
  241.     status = SUCCESS;
  242.     goto exit;
  243.     }
  244.  
  245.     /*
  246.      * Pause the write back during the truncate to sync access to
  247.      * file index.
  248.      */
  249.     Fscache_PreventWriteBacks(&handlePtr->cacheInfo);
  250.     status = LfsFile_TruncIndex(lfsPtr, handlePtr, size);
  251.     if (status == SUCCESS) {
  252.     if (size == 0) {
  253.         int    newVersion;
  254.         LFS_STATS_INC(lfsPtr->stats.desc.truncSizeZero);
  255.         status = LfsDescMapIncVersion(lfsPtr, 
  256.             handlePtr->hdr.fileID.minor, &newVersion);
  257.     }
  258.     descPtr->lastByte = newLastByte;
  259.     descPtr->descModifyTime = Fsutil_TimeInSeconds();
  260.     if (delete) {
  261.         /*
  262.          * XXX - need sync here. 
  263.          */
  264.         descPtr->flags &= ~FSDM_FD_DIRTY;
  265.     } else {
  266.         descPtr->flags |= FSDM_FD_SIZE_DIRTY;
  267.     }
  268.     }
  269.     Fscache_AllowWriteBacks(&handlePtr->cacheInfo);
  270. exit:
  271.     if (delete) { 
  272.     LFS_STATS_INC(lfsPtr->stats.desc.delete);
  273.     /*
  274.      * XXX - need sync here. 
  275.      */
  276.     descPtr->flags &= ~FSDM_FD_DIRTY;
  277.     status = Fscache_RemoveFileFromDirtyList(&handlePtr->cacheInfo);
  278.     } else {
  279.     if (descPtr->flags & FSDM_FD_DIRTY) {
  280.         status = Fscache_PutFileOnDirtyList(&handlePtr->cacheInfo, 
  281.                 FSCACHE_FILE_DESC_DIRTY);
  282.     }
  283.     }
  284.     return status;
  285. }
  286.  
  287. /*
  288.  *----------------------------------------------------------------------
  289.  *
  290.  * Lfs_FileDescInit() --
  291.  *
  292.  *    Initialize a new file descriptor.
  293.  *
  294.  * Results:
  295.  *    SUCCESS
  296.  *
  297.  * Side effects:
  298.  *    The file decriptor is initialized.
  299.  *
  300.  *----------------------------------------------------------------------
  301.  */
  302. /*ARGSUSED*/
  303. ReturnStatus
  304. Lfs_FileDescInit(domainPtr, fileNumber, type, permissions, uid, gid, fileDescPtr)
  305.     Fsdm_Domain     *domainPtr;    /* Domain of the file */
  306.     int            fileNumber;     /* Number of file descriptor */
  307.     int            type;        /* Type of the file */
  308.     int            permissions;    /* Permission bits for the file */
  309.     int            uid;        /* Owner ID for the file */
  310.     int            gid;        /* Group ID for the file */
  311.     Fsdm_FileDescriptor    *fileDescPtr;    /* File descriptor structure to
  312.                        initialize. */
  313. {
  314.     register int index;
  315.     LFS_STATS_INC((LfsFromDomainPtr(domainPtr))->stats.desc.inits);
  316.  
  317.     fileDescPtr->magic = FSDM_FD_MAGIC;
  318.     fileDescPtr->flags = FSDM_FD_ALLOC|FSDM_FD_DIRTY;
  319.     fileDescPtr->fileType = type;
  320.     fileDescPtr->permissions = permissions;
  321.     fileDescPtr->uid = uid;
  322.     fileDescPtr->gid = gid;
  323.     fileDescPtr->lastByte = -1;
  324.     fileDescPtr->lastByteXtra = 0;
  325.     fileDescPtr->firstByte = -1;
  326.     fileDescPtr->userType = FS_USER_TYPE_UNDEFINED;
  327.     fileDescPtr->numLinks = 1;
  328.  
  329.     /*
  330.      * Clear out device info.  It is set up properly by the make-device routine.
  331.      */
  332.     fileDescPtr->devServerID = -1;
  333.     fileDescPtr->devType = -1;
  334.     fileDescPtr->devUnit = -1;
  335.  
  336.     /*
  337.      * Set the time stamps.  These times should come from the client.
  338.      */
  339.     fileDescPtr->createTime = Fsutil_TimeInSeconds();
  340.     fileDescPtr->accessTime = fileDescPtr->createTime;
  341.     fileDescPtr->descModifyTime = fileDescPtr->createTime;
  342.     fileDescPtr->dataModifyTime = fileDescPtr->createTime;
  343.  
  344.     for (index = 0; index < FSDM_NUM_DIRECT_BLOCKS ; index++) {
  345.     fileDescPtr->direct[index] = FSDM_NIL_INDEX;
  346.     }
  347.     for (index = 0; index < FSDM_NUM_INDIRECT_BLOCKS ; index++) {
  348.     fileDescPtr->indirect[index] = FSDM_NIL_INDEX;
  349.     }
  350.     fileDescPtr->numKbytes = 0;
  351.     /*
  352.      * Give this new file a new version number.  The increment is by 2 to
  353.      * ensure that a client invalidates any cache blocks associated with
  354.      * the previous incarnation of the file.  Remember that when a client
  355.      * opens for writing a version number 1 greater means that its old
  356.      * cache blocks are still ok, and also remember that clients with
  357.      * clean blocks are not told when a file is deleted.
  358.      */
  359.     fileDescPtr->version = LfsGetCurrentTimestamp(LfsFromDomainPtr(domainPtr));
  360.     return(SUCCESS);
  361. }
  362.  
  363. /*
  364.  * @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
  365.  * End of routines exported to higher levels of the file system.
  366.  * @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
  367.  *
  368.  * Start of LFS private routines. 
  369.  */
  370.  
  371. /*
  372.  *----------------------------------------------------------------------
  373.  *
  374.  * LfsDescCacheInit --
  375.  *
  376.  *    Initialize the descriptor cache for a file system.
  377.  *
  378.  * Results:
  379.  *    None.
  380.  *
  381.  * Side effects:
  382.  *    None.
  383.  *
  384.  *----------------------------------------------------------------------
  385.  */
  386. void
  387. LfsDescCacheInit(lfsPtr)
  388.     Lfs        *lfsPtr;
  389. {
  390.     Fscache_Attributes        attr;
  391.     /*
  392.      * Initialize the file handle used to cache descriptor blocks.
  393.      */
  394.  
  395.     bzero((char *)(&lfsPtr->descCache.handle),sizeof(lfsPtr->descCache.handle));
  396.     lfsPtr->descCache.handle.hdr.fileID.serverID = rpc_SpriteID;
  397.     lfsPtr->descCache.handle.hdr.fileID.major = lfsPtr->domainPtr->domainNumber;
  398.     lfsPtr->descCache.handle.hdr.fileID.minor = 0;
  399.     lfsPtr->descCache.handle.hdr.fileID.type = FSIO_LCL_FILE_STREAM;
  400.     lfsPtr->descCache.handle.descPtr = (Fsdm_FileDescriptor *)NIL;
  401.  
  402.  
  403.     bzero((Address)&attr, sizeof(attr));
  404.     attr.lastByte = 0x7fffffff;
  405.     Fscache_FileInfoInit(&lfsPtr->descCache.handle.cacheInfo,
  406.             (Fs_HandleHeader *) &lfsPtr->descCache.handle,
  407.             0, TRUE, &attr, lfsPtr->domainPtr->backendPtr);
  408.  
  409. }
  410.  
  411. /*
  412.  *----------------------------------------------------------------------
  413.  *
  414.  * LfsDescCacheDestory --
  415.  *
  416.  *    Destory the descriptor cache for a file system.
  417.  *
  418.  * Results:
  419.  *    None.
  420.  *
  421.  * Side effects:
  422.  *    None.
  423.  *
  424.  *----------------------------------------------------------------------
  425.  */
  426. void
  427. LfsDescCacheDestory(lfsPtr)
  428.     Lfs        *lfsPtr;
  429. {
  430.  
  431.     Fscache_FileInvalidate(&lfsPtr->descCache.handle.cacheInfo, 0, 
  432.         FSCACHE_LAST_BLOCK);
  433.  
  434. }
  435.  
  436. /*
  437.  *----------------------------------------------------------------------
  438.  *
  439.  * LfsDescCacheBlockInit --
  440.  *
  441.  *    Initialize a block into the descriptor cache for a file system.
  442.  *
  443.  * Results:
  444.  *    NIL if the block couldn't be initialized. A clientData otherwise. 
  445.  *
  446.  * Side effects:
  447.  *    Cache block is fetched and held.
  448.  *
  449.  *----------------------------------------------------------------------
  450.  */
  451.  
  452. ClientData
  453. LfsDescCacheBlockInit(lfsPtr, diskBlockAddr, cantBlock, blockStartPtr)
  454.     Lfs        *lfsPtr;    /* File system. */
  455.     LfsDiskAddr    diskBlockAddr;    /* Descriptor cache block address. */
  456.     Boolean     cantBlock;    /* TRUE if process can`t block. */
  457.     char    **blockStartPtr;    /* OUT: pointer to lock's contents. */
  458. {
  459.     Fscache_Block    *blockPtr;
  460.     int            blockNum;
  461.     Boolean    found;
  462.  
  463.     blockNum = LfsDiskAddrToOffset(diskBlockAddr);
  464.     Fscache_FetchBlock(&lfsPtr->descCache.handle.cacheInfo,
  465.         blockNum, (FSCACHE_DESC_BLOCK|FSCACHE_CANT_BLOCK| (cantBlock ? FSCACHE_DONT_BLOCK:0)),
  466.             &blockPtr, &found);
  467.     if (blockPtr == (Fscache_Block *) NIL) {
  468.     return (ClientData) blockPtr;
  469.     }
  470.     if (!found) {
  471.     if ((*blockStartPtr) != (char *) NIL) {
  472.         bcopy(*blockStartPtr, blockPtr->blockAddr,
  473.            lfsPtr->fileLayout.params.descPerBlock * 
  474.             LFS_FILE_DESC_SIZE);
  475.     } else {
  476.         bzero(blockPtr->blockAddr, lfsPtr->fileLayout.params.descPerBlock * 
  477.             LFS_FILE_DESC_SIZE);
  478.     }
  479.     Fscache_IODone(blockPtr);
  480.     } else {
  481. #ifdef ERROR_CHECK
  482.     if (((*blockStartPtr) != (char *) NIL) && 
  483.         (bcmp(*blockStartPtr, blockPtr->blockAddr, 
  484.         lfsPtr->fileLayout.params.descPerBlock * LFS_FILE_DESC_SIZE) 
  485.         != 0)) {
  486.         panic("LfsDescCacheBlockInit found wrong block\n");
  487.     }
  488. #endif
  489.     }
  490.     if (*blockStartPtr == (char *) NIL) { 
  491.     *blockStartPtr = blockPtr->blockAddr;
  492.     }
  493.     return (ClientData) blockPtr;
  494. }
  495.  
  496.  
  497. /*
  498.  *----------------------------------------------------------------------
  499.  *
  500.  * LfsDescCacheBlockRelease --
  501.  *
  502.  *    Release a desc cache block return by LfsDescCacheBlockInit.
  503.  *
  504.  * Results:
  505.  *    void
  506.  *
  507.  * Side effects:
  508.  *
  509.  *----------------------------------------------------------------------
  510.  */
  511.  
  512. void
  513. LfsDescCacheBlockRelease(lfsPtr, clientData, deleteBlock)
  514.     Lfs        *lfsPtr;
  515.     ClientData    clientData;
  516.     Boolean    deleteBlock;     /* TRUE if block should be deleted. */
  517. {
  518.     Fscache_Block    *blockPtr = (Fscache_Block *) clientData;
  519.     Fscache_UnlockBlock(blockPtr,(time_t)0, -1, FS_BLOCK_SIZE, 
  520.         deleteBlock ? FSCACHE_DELETE_BLOCK : 0);
  521. }
  522.  
  523.